package com.ruoyi.common.pay.wxs;

import com.alibaba.fastjson.JSON;
import com.tencent.cloudpay.CloudPay;
import com.tencent.cloudpay.config.Account;
import com.tencent.cloudpay.config.Terminal;
import com.tencent.cloudpay.param.*;
import com.tencent.cloudpay.pojo.*;
import com.tencent.cloudpay.utils.CommonUtils;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;

public class CloudPayDemo {
    String out_trade_no_prefix = "sz0100lmnx2--";

    @BeforeClass
    public static void setup() {
        Account account = new Account("sz013NzuonO6CMJd0rCB",
                "sz01ELTR281OFpmdAp6J",
                "sz019xAikh2E0VfLwLfi",
                "5973",
                "17352");

        String authenKey = "lSCp1M5grGWFD7rJzaZaqixsvOhORp2P"; //

        Terminal terminal = new Terminal(2,
                900,
                "01-01-01-01-01-01",
                "192.168.1.1");


        CloudPay.init(account, authenKey, terminal);
    }

    @Test
    public void testPing() {
        int ret = CloudPay.getInstance().ping();
        assertEquals(0, ret);

        // 切换为上海的域名
        ret = CloudPay.getInstance().ping("https://sh.pay.qcloud.com");
        assertEquals(0, ret);
    }

    private String wxMicroPayPayOutTradeNo = out_trade_no_prefix + "128172";

    @Test
    public void testMicroPayWx() {
        MicroPayRequest microPayRequest = new MicroPayRequest(1,
                "134566739046960585", // 付款码
                2,
                wxMicroPayPayOutTradeNo,
                "测试",
                CommonUtils.generateNonceStr()
        );

        // 设置商品详情
        microPayRequest.setDetail(getDetail());

        MicroPayResponse microPayResponse = CloudPay.getInstance().microPay(microPayRequest);

        int state = microPayResponse.getOrder().getState();
        assert (state == State.kCloudPaySdkLocalStateUserPaying ||
                state == State.kCloudPaySdkLocalStateSuccess ||
                state == State.kCloudPaySdkLocalStateRefund);

    }

    private Detail getDetail() {
        Detail detail = new Detail();
        detail.setCost_price(1);
        detail.setReceipt_id("xxxx_recepid_123");


        List<GoodsDetail> goodsDetails = new ArrayList<GoodsDetail>();

        GoodsDetail goods = new GoodsDetail();

        goods.setGoods_id("123");
        goods.setGoods_name("商品名字");
        goods.setPrice(10);
        goods.setQuantity(2);
        goodsDetails.add(goods);

        detail.setGoods_detail(goodsDetails);

        return detail;
    }

    private String aliMicroPayOutTradeNo = out_trade_no_prefix + "12u1i2";

    @Test
    public void testMicroPayAli() {
        MicroPayRequest microPayRequest = new MicroPayRequest(2,
                "289638318969073042",
                1,
                aliMicroPayOutTradeNo,
                "test",
                CommonUtils.generateNonceStr()
        );

        MicroPayResponse microPayResponse = CloudPay.getInstance().microPay(microPayRequest);

        int state = microPayResponse.getOrder().getState();
        assert (state == State.kCloudPaySdkLocalStateUserPaying ||
                state == State.kCloudPaySdkLocalStateSuccess ||
                state == State.kCloudPaySdkLocalStateRefund);
    }

    private String scanCodePayOutTradeNo = out_trade_no_prefix + "13819";

    @Test
    public void testScanCodePay() {
        ScanCodePayRequest scanCodePayRequest = new ScanCodePayRequest();

        scanCodePayRequest.setPay_platform(1);
        scanCodePayRequest.setTotal_fee(1);
        scanCodePayRequest.setOut_trade_no(scanCodePayOutTradeNo);
        scanCodePayRequest.setBody("测试");
        scanCodePayRequest.setProduct_id("product_id");

        String codeUrl = CloudPay.getInstance().scanCodePay(scanCodePayRequest);
        System.out.println(codeUrl);
    }

    private String wxOfficalAccountPayOutTradeNo = out_trade_no_prefix + "1y1129038";

    @Test
    public void testOfficalAccountWxPay() {
        payEn officialAccountPayRequest = new payEn();
        officialAccountPayRequest.setPay_platform(1);
        officialAccountPayRequest.setTotal_fee(2);
        officialAccountPayRequest.setBody("test");
        officialAccountPayRequest.setWx_open_id("ovUXa1K9Qn1E4j0oyPIOPVvnO0hc");
        officialAccountPayRequest.setOut_trade_no(wxOfficalAccountPayOutTradeNo+(int)(Math.random()*1000));
        officialAccountPayRequest.setDevice_id("1111111111111111");

        OfficialAccountPayResponse response = CloudPay.getInstance().officialAccountPay(officialAccountPayRequest);
        System.out.println(JSON.toJSONString(response.getJsapi_args().getWxpay()));
        assertNotNull(response.getJsapi_args());
    }

    private String aliOfficalAccountPayOutTradeNo = out_trade_no_prefix + "sdnnni890d";

    @Test
    public void testOfficalAccountAliPay() {
        OfficialAccountPayRequest officialAccountPayRequest = new OfficialAccountPayRequest();
        officialAccountPayRequest.setPay_platform(2);
        officialAccountPayRequest.setTotal_fee(1);
        officialAccountPayRequest.setBody("测试");
        officialAccountPayRequest.setAli_user_id("2088902973419255");
        officialAccountPayRequest.setOut_trade_no(aliOfficalAccountPayOutTradeNo);
        OfficialAccountPayResponse response = CloudPay.getInstance().officialAccountPay(officialAccountPayRequest);

        assertNotNull(response.getJsapi_args());
        System.out.println(response.getOrder().getState());

        QueryOrderRequest queryOrderRequest = new QueryOrderRequest(aliOfficalAccountPayOutTradeNo, "测试");
        QueryOrderResponse queryOrderResponse = CloudPay.getInstance().queryOrder(queryOrderRequest);
        Order order = queryOrderResponse.getOrder();
        System.out.println(queryOrderResponse.getOrder().getState());
    }

    @Test
    public void testCloseOrder() {
        CloseOrderRequest closeOrderRequest = new CloseOrderRequest();
        closeOrderRequest.setPay_platform(1);
        closeOrderRequest.setOut_trade_no(scanCodePayOutTradeNo);
        closeOrderRequest.setTrade_type(TradeType.ScanCodePay);

        Boolean result = CloudPay.getInstance().closeOrder(closeOrderRequest);
        assertTrue(result);
    }

    @Test
    public void testQueryOrder() {

        QueryOrderRequest queryOrderRequest = new QueryOrderRequest(wxMicroPayPayOutTradeNo, "测试");
        QueryOrderResponse queryOrderResponse = CloudPay.getInstance().queryOrder(queryOrderRequest);
        Order order = queryOrderResponse.getOrder();

        assertNotNull(order);

        assertEquals(1, order.getPay_platform());
        assertEquals(2, order.getTotal_fee());
        assertEquals(wxMicroPayPayOutTradeNo, order.getOut_trade_no());

        assertGoodsDetail(getDetail(), order.getDetail());
    }

    private void assertGoodsDetail(Detail detail1, Detail detail2) {
        if (detail1 == null) {
            assertNull(detail2);
            return;
        }
        assertEquals(detail1.getCost_price(), detail2.getCost_price());
        assertEquals(detail1.getReceipt_id(), detail2.getReceipt_id());

        List<GoodsDetail> goodsList1 = detail1.getGoods_detail();
        List<GoodsDetail> goodsList2 = detail2.getGoods_detail();

        assertEquals(goodsList1.size(), goodsList2.size());

        if (goodsList1.size() > 0) {
            GoodsDetail goods1 = goodsList1.get(0);
            GoodsDetail goods2 = goodsList2.get(0);

            assertEquals(goods1.getGoods_id(), goods2.getGoods_id());
            assertEquals(goods1.getGoods_name(), goods2.getGoods_name());
            assertEquals(goods1.getPrice(), goods2.getPrice());
            assertEquals(goods1.getQuantity(), goods2.getQuantity());
        }
    }

    private String out_refund_no_1 = out_trade_no_prefix + "190suqiow";
    private String out_refund_no_2 = out_trade_no_prefix + "788912n9fis4";

    @Test
    public void testRefund() {
        RefundRequest refundRequest = new RefundRequest();
        refundRequest.setOut_trade_no(wxMicroPayPayOutTradeNo);
        refundRequest.setNonce_str(CommonUtils.generateNonceStr());
        refundRequest.setTotal_fee(2);
        refundRequest.setPay_platform(1);
        refundRequest.setRefund_fee(1);

        // 第一笔退款单
        refundRequest.setOut_refund_no(out_refund_no_1);
        int status = CloudPay.getInstance().refund(refundRequest);
        assertEquals(0, status);

        // 第二笔退款单
        refundRequest.setOut_refund_no(out_refund_no_2);
        status = CloudPay.getInstance().refund(refundRequest);
        assertEquals(0, status);
    }

    @Test
    public void testQueryRefund() {
        QueryRefundRequest queryRefundRequest = new QueryRefundRequest();
        queryRefundRequest.setNonce_str(CommonUtils.generateNonceStr());
        queryRefundRequest.setOut_trade_no(wxMicroPayPayOutTradeNo);
        queryRefundRequest.setPay_platform(1);

        QueryRefundResponse queryRefundResponse = CloudPay.getInstance().queryRefund(queryRefundRequest);
        List<RefundOrder> refundOrder = queryRefundResponse.getRefund_order();
        assertNotNull(refundOrder);
        assertEquals(2, refundOrder.size());

        assertQueryRefund(refundOrder.get(0), out_refund_no_1);
        assertQueryRefund(refundOrder.get(1), out_refund_no_2);
    }


    private void assertQueryRefund(RefundOrder refundOrder, String refund_order_no) {
        int state = refundOrder.getState();
        assertTrue(state == State.kCloudPaySdkRefundLocalStateSuccess || state == State.kCloudPaySdkRefundLocalStateProcessing);
        assertEquals(1, refundOrder.getPay_platform());
        assertEquals(2, refundOrder.getTotal_fee());
        assertEquals(1, refundOrder.getRefund_fee());
        assertEquals(wxMicroPayPayOutTradeNo, refundOrder.getOut_trade_no());
        assertEquals(refund_order_no, refundOrder.getOut_refund_no());
        assertTrue(refundOrder.getRefund_id().length() != 0);
    }
}
